package br.com.skolar.client.view;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import br.com.skolar.client.Answer;
import br.com.skolar.client.Question;
import br.com.skolar.client.events.LoadAnswersEvent;
import br.com.skolar.client.events.QuestionsLoadedEvent;
import br.com.skolar.client.events.SaveAnswerEvent;
import br.com.skolar.client.events.SaveQuestionEvent;
import br.com.skolar.client.framework.ButtonHandler;
import br.com.skolar.client.framework.ButtonPanel;
import br.com.skolar.client.framework.Event;
import br.com.skolar.client.framework.EventBus;
import br.com.skolar.client.framework.ParamCommand;
import br.com.skolar.client.framework.rtf.RichTextEditor;
import br.com.skolar.client.framework.view.DataGridWidget;
import br.com.skolar.client.framework.view.DataWidget;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DomEvent;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLTable.Cell;
import com.google.gwt.user.client.ui.HTMLTable.RowFormatter;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.LazyPanel;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;

public class QuestionsView extends Composite {
	private final EventBus eventBus;
	private final SkolarMessages messages;

	private QuestionsPanel questionsPanel = new QuestionsPanel();
	
	private PushButton cadastreButton;
	private QuestionTable questionTable;

	private FlexTable formTable;
	private QuestionForm form;
	private ButtonPanel formButtons;

	@Inject
	public QuestionsView(EventBus eventBus, SkolarMessages messages) {
		this.eventBus = eventBus;
		this.messages = messages;
		
		VerticalPanel vp = new VerticalPanel();
		vp.add(new HTML("<h2>" + messages.welcome() + "</h2>"));
		vp.add(questionsPanel);
		initWidget(vp);
		
		RootPanel.get("content").add(this);
		
		eventBus.addHandler(QuestionsLoadedEvent.class, new Event.Handler<QuestionsLoadedEvent>() {
			@Override
			public void onEvent(QuestionsLoadedEvent e) {
				questionsPanel.populate(e.questions);
			}
		});
	}
	
	class QuestionsPanel extends LazyPanel {
		@Override
		protected Widget createWidget() {
			cadastreButton = new PushButton(messages.cadastre());
			ButtonHandler h = new ButtonHandler() {
				@Override
				protected void onEvent(DomEvent e) {
					if (form==null)
						form = new QuestionForm();
					form.bind(new Question(), new ArrayList());
				}
			};
			cadastreButton.addKeyUpHandler(h);
			cadastreButton.addClickHandler(h);
			cadastreButton.setWidth("125px");

			formTable = new FlexTable();
			formTable.setWidth("100%");
			
			questionTable = new QuestionTable();
			questionTable.setWidth("540px");
			
			searchView();
			
			return formTable;
		}
		
		public void populate(Collection<Question> questions) {
			setVisible(true);
			questionTable.populate(questions);
		}
	}
	
	private void searchView() {
		formTable.setWidget(0, 0, cadastreButton);
		formTable.setWidget(1, 0, questionTable);
	}

	private void editView() {
		formTable.setWidget(0, 0, form);
		formTable.setText(1, 0, "");
	}
	
	class QuestionTable extends DataGridWidget<Question> {
		@Override
		protected String getEmptyResultMessageText() {
			return messages.emptyResult();
		}

		@Override
		protected String[] getHeaders() {
			return new String[] {
				"Questão"	
			};
		}

		@Override
		protected Widget[] getData(Question q) {
			String d = q.getDescription();
			int trim = d.length();
			if (trim>255)
				d = d.substring(0, 255).concat("...");
			return new Widget[] { new HTML(d) };
		}

		@Override
		protected void handleSelection(int row, int col) {
			eventBus.fireEvent(new LoadAnswersEvent(selected, new ParamCommand<List<Answer>>() {
				@Override
				public void execute(List<Answer> answers) {
					if (form==null)
						form = new QuestionForm();
					form.bind(selected, answers);
				}
			}));
		}
	}
	
	class QuestionForm extends LazyPanel {
		Question question;
		List<Answer> answers;
		Answer answer;
		
		int currentRow;
		
		VerticalPanel rtePanel;
		RichTextEditor rte;
		FlexTable table;
		PushButton addButton;
		
		@Override
		protected Widget createWidget() {
			rte = new RichTextEditor();
			rtePanel = new VerticalPanel();
			rtePanel.setWidth("100%");
			rtePanel.add(rte);
			
			formButtons = new ButtonPanel(messages.cancel(), messages.save());
			formButtons.setCancelHandler(new ButtonHandler() {
				@Override
				protected void onEvent(DomEvent e) {
					e.stopPropagation();
					detachRte(true);
					currentRow = 0;
				}
			}).setSaveHandler(new ButtonHandler() {
				@Override
				protected void onEvent(DomEvent e) {
					e.stopPropagation();
					if (rte.isEmpty()) {
						Window.alert("Preencha o campo de texto");
						formButtons.enableButtons(true);
					}
					else if (currentRow==1) {
						form.question.setDescription(rte.getHTML());
						eventBus.fireEvent(new SaveQuestionEvent(form.question,
						new ParamCommand<Question>() {
							@Override
							public void execute(Question t) {
								form.onSave(t);
							}
						}));
					}
					else {
						form.answer.setDescription(rte.getHTML());
						eventBus.fireEvent(new SaveAnswerEvent(form.answer,
						new ParamCommand<Answer>() {
							@Override
							public void execute(Answer a) {
								form.onSave(a);
							}
						}));
					}
				}
			});
			rtePanel.add(formButtons);
			rtePanel.setCellHorizontalAlignment(formButtons, VerticalPanel.ALIGN_RIGHT);
			
			table = new FlexTable();
			table.setWidth("100%");
			table.setStyleName(DataWidget.DATAGRID);
			table.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					Cell c = table.getCellForEvent(event);
					int r = c.getRowIndex();
					if (r!=0 && r!=2 && r!=table.getRowCount()-1 && r!=currentRow)
						select(c.getRowIndex());
				}
			});
			
			ButtonHandler h = new ButtonHandler() {
				@Override
				protected void onEvent(DomEvent e) {
					e.stopPropagation();
					answer = new Answer(question.getId());
					answers.add(answer);
					select(table.insertRow(table.getRowCount()-1));
				}
			};
			addButton = new PushButton(messages.add());
			addButton.setWidth("100px");
			addButton.addClickHandler(h);
			addButton.addKeyUpHandler(h);
			
			return table;
		}

		protected void select(int row) {
			if (rte.isAttached())
				detachRte(true);
			
			addButton.setEnabled(false);
			currentRow = row;
			table.setWidget(row, 0, rtePanel);
			
			answer = null;
			if (row!=1)
				answer = answers.get(row-3);
			rte.setHTML(row==1 ? question.getDescription() : answer.getDescription());
		}
		
		private void detachRte(boolean cancelled) {
			if (cancelled) {
				if (answer==null) {
					if (question.getId()==null)
						searchView();
					else table.setHTML(currentRow, 0, question.getDescription());
				}
				else if (answer.getId()==null)
					table.removeRow(currentRow);
				else table.setHTML(currentRow, 0, answer.getDescription());
			}
			else {
				if (new HTML(rte.getHTML()).getText().length()==0) {
					Window.alert("Preencha o campo de texto");
					return;
				}
				String html = rte.getHTML();
				
				// gets the new value before move rte to selected line
				if (currentRow==1)
					question.setDescription(html);
				else if (!answers.isEmpty()) 
					answer.setDescription(html);
			}
			addButton.setEnabled(true);
		}

		void bind(Question q, List<Answer> answers) {
			this.question = q;
			this.answers = answers;

			setVisible(true);
			editView();

			table.removeAllRows();
			
			table.setText(0, 0, "Enunciado");
			RowFormatter rf = table.getRowFormatter();
			rf.setStyleName(0, DataWidget.DATAGRID_HEADER);
			
			if (q.getId()==null) {
				currentRow = 1;
				table.setWidget(1, 0, rtePanel);
			}
			else {
				table.setHTML(1, 0, q.getDescription());
				table.setText(2, 0, "Alternativas");
				rf.setStyleName(2, DataWidget.DATAGRID_HEADER);
				int i = 3;
				for (Answer a : answers)
					table.setHTML(i++, 0, a.getDescription());

				table.setWidget(i, 0, addButton);
				table.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_CENTER);
			}
		}

		protected void onSave(Question q) {
			if (question.getId()==null)
				bind(q, new ArrayList<Answer>());
			else table.setHTML(1, 0, q.getDescription());
			
			this.question = q;
			currentRow = 0;
			formButtons.enableButtons(true);
			addButton.setEnabled(true);
		}
		
		protected void onSave(Answer a) {
			int i = answers.indexOf(answer);
			answers.remove(i);
			answers.add(i, a);
			answer = a;
			
			table.setHTML(currentRow, 0, a.getDescription());
			currentRow = 0;
			
			formButtons.enableButtons(true);
			addButton.setEnabled(true);
		}
	}
}